From 27d7304ed79a09ab0fbf14269154a4a46a20e170 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 10 Mar 2006 16:00:36 +0100 Subject: [PATCH] Replace memory_op subcommands reserved_phys_area and map_shared_info with new subcommand add_to_physmap. This changes the domain0 tools interface, but only when building shadow-translate-mode guests. Signed-off-by: Keir Fraser --- tools/libxc/xc_linux_build.c | 39 ++++++++----- tools/libxc/xc_private.c | 8 +-- xen/arch/x86/mm.c | 93 +++++++++++-------------------- xen/include/asm-x86/grant_table.h | 3 - xen/include/asm-x86/page.h | 4 ++ xen/include/public/memory.h | 47 ++++++---------- 6 files changed, 83 insertions(+), 111 deletions(-) diff --git a/tools/libxc/xc_linux_build.c b/tools/libxc/xc_linux_build.c index f5894d2724..1f91e5e4a4 100644 --- a/tools/libxc/xc_linux_build.c +++ b/tools/libxc/xc_linux_build.c @@ -863,8 +863,7 @@ static int setup_guest(int xc_handle, if ( shadow_mode_enabled ) { - struct xen_reserved_phys_area xrpa; - struct xen_map_shared_info xmsi; + struct xen_add_to_physmap xatp; /* Enable shadow translate mode */ if ( xc_shadow_control(xc_handle, dom, @@ -875,25 +874,35 @@ static int setup_guest(int xc_handle, goto error_out; } - /* Find the shared info frame. It's guaranteed to be at the - start of the PFN hole. */ - xrpa.domid = dom; - xrpa.idx = 0; - rc = xc_memory_op(xc_handle, XENMEM_reserved_phys_area, &xrpa); + guest_shared_info_mfn = (vsharedinfo_start-dsi.v_start) >> PAGE_SHIFT; + + /* Map shared info frame into guest physmap. */ + xatp.domid = dom; + xatp.space = XENMAPSPACE_shared_info; + xatp.idx = 0; + xatp.gpfn = guest_shared_info_mfn; + rc = xc_memory_op(xc_handle, XENMEM_add_to_physmap, &xatp); if ( rc != 0 ) { - PERROR("Cannot find shared info pfn"); + PERROR("Cannot map shared info pfn"); goto error_out; } - guest_shared_info_mfn = (vsharedinfo_start-dsi.v_start) >> PAGE_SHIFT; - xmsi.domid = dom; - xmsi.pfn = guest_shared_info_mfn; - rc = xc_memory_op(xc_handle, XENMEM_map_shared_info, &xmsi); - if ( rc != 0 ) + /* Map grant table frames into guest physmap. */ + for ( i = 0; ; i++ ) { - PERROR("Cannot map shared info pfn"); - goto error_out; + xatp.domid = dom; + xatp.space = XENMAPSPACE_grant_table; + xatp.idx = i; + xatp.gpfn = nr_pages + i; + rc = xc_memory_op(xc_handle, XENMEM_add_to_physmap, &xatp); + if ( rc != 0 ) + { + if ( errno == EINVAL ) + break; /* done all grant tables */ + PERROR("Cannot map grant table pfn"); + goto error_out; + } } } else diff --git a/tools/libxc/xc_private.c b/tools/libxc/xc_private.c index 6234162b73..d4b34a8f46 100644 --- a/tools/libxc/xc_private.c +++ b/tools/libxc/xc_private.c @@ -231,8 +231,8 @@ int xc_memory_op(int xc_handle, goto out1; } break; - case XENMEM_reserved_phys_area: - if ( mlock(arg, sizeof(struct xen_reserved_phys_area)) ) + case XENMEM_add_to_physmap: + if ( mlock(arg, sizeof(struct xen_add_to_physmap)) ) { PERROR("Could not mlock"); goto out1; @@ -277,8 +277,8 @@ int xc_memory_op(int xc_handle, safe_munlock(xmml->extent_start, xmml->max_extents * sizeof(unsigned long)); break; - case XENMEM_reserved_phys_area: - safe_munlock(arg, sizeof(struct xen_reserved_phys_area)); + case XENMEM_add_to_physmap: + safe_munlock(arg, sizeof(struct xen_add_to_physmap)); break; case XENMEM_translate_gpfn_list: safe_munlock(trans->mfn_list, trans->nr_gpfns * sizeof(long)); diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index fd6f323514..c5d958a884 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -234,6 +234,8 @@ void share_xen_page_with_guest( if ( page_get_owner(page) == d ) return; + set_gpfn_from_mfn(page_to_mfn(page), INVALID_M2P_ENTRY); + spin_lock(&d->page_alloc_lock); /* The incremented type count pins as writable or read-only. */ @@ -2817,81 +2819,54 @@ long do_update_descriptor(u64 pa, u64 desc) long arch_memory_op(int op, GUEST_HANDLE(void) arg) { - unsigned long pfn; - struct domain *d; - unsigned int i; - switch ( op ) { - case XENMEM_reserved_phys_area: { - struct xen_reserved_phys_area xrpa; + case XENMEM_add_to_physmap: + { + struct xen_add_to_physmap xatp; + unsigned long mfn = 0, gpfn; + struct domain *d; - if ( copy_from_guest(&xrpa, arg, 1) ) + if ( copy_from_guest(&xatp, arg, 1) ) return -EFAULT; - /* No guest has more than one reserved area. */ - if ( xrpa.idx != 0 ) - return -ESRCH; - - if ( (d = find_domain_by_id(xrpa.domid)) == NULL ) - return -ESRCH; - - /* Only initialised translated guests have a reserved area. */ - if ( !shadow_mode_translate(d) || (d->max_pages == 0) ) - { - put_domain(d); + if ( (d = find_domain_by_id(xatp.domid)) == NULL ) return -ESRCH; - } - LOCK_BIGLOCK(d); - if ( d->arch.first_reserved_pfn == 0 ) + switch ( xatp.space ) { - d->arch.first_reserved_pfn = pfn = d->max_pages; - for ( i = 0; i < NR_GRANT_FRAMES; i++ ) - guest_physmap_add_page( - d, pfn + i, gnttab_shared_mfn(d, d->grant_table, i)); + case XENMAPSPACE_shared_info: + if ( xatp.idx == 0 ) + mfn = virt_to_mfn(d->shared_info); + break; + case XENMAPSPACE_grant_table: + if ( xatp.idx < NR_GRANT_FRAMES ) + mfn = virt_to_mfn(d->grant_table->shared) + xatp.idx; + break; + default: + break; } - UNLOCK_BIGLOCK(d); - - xrpa.first_gpfn = d->arch.first_reserved_pfn; - xrpa.nr_gpfns = NR_GRANT_FRAMES; - - put_domain(d); - - if ( copy_to_guest(arg, &xrpa, 1) ) - return -EFAULT; - - break; - } - - case XENMEM_map_shared_info: { - struct xen_map_shared_info xmsi; - - if ( copy_from_guest(&xmsi, arg, 1) ) - return -EFAULT; - - if ( (d = find_domain_by_id(xmsi.domid)) == NULL ) - return -ESRCH; - - /* Only initialised translated guests can set the shared_info - * mapping. */ - if ( !shadow_mode_translate(d) || (d->max_pages == 0) ) + + if ( !shadow_mode_translate(d) || (mfn == 0) ) { - put_domain(d); - return -ESRCH; - } - - if ( xmsi.pfn > d->max_pages ) { put_domain(d); return -EINVAL; } LOCK_BIGLOCK(d); + /* Remove previously mapped page if it was present. */ - if ( mfn_valid(gmfn_to_mfn(d, xmsi.pfn)) ) - guest_remove_page(d, xmsi.pfn); - guest_physmap_add_page(d, xmsi.pfn, - virt_to_maddr(d->shared_info) >> PAGE_SHIFT); + if ( mfn_valid(gmfn_to_mfn(d, xatp.gpfn)) ) + guest_remove_page(d, xatp.gpfn); + + /* Unmap from old location, if any. */ + gpfn = get_gpfn_from_mfn(mfn); + if ( gpfn != INVALID_M2P_ENTRY ) + guest_physmap_remove_page(d, gpfn, mfn); + + /* Map at new location. */ + guest_physmap_add_page(d, xatp.gpfn, mfn); + UNLOCK_BIGLOCK(d); put_domain(d); diff --git a/xen/include/asm-x86/grant_table.h b/xen/include/asm-x86/grant_table.h index 038819ba68..3d55e636e1 100644 --- a/xen/include/asm-x86/grant_table.h +++ b/xen/include/asm-x86/grant_table.h @@ -26,9 +26,6 @@ int steal_page_for_grant_transfer( share_xen_page_with_guest( \ virt_to_page((char *)(t)->shared + ((i) * PAGE_SIZE)), \ (d), XENSHARE_writable); \ - set_gpfn_from_mfn( \ - (virt_to_maddr((t)->shared) >> PAGE_SHIFT) + (i), \ - INVALID_M2P_ENTRY); \ } while ( 0 ) #define gnttab_shared_mfn(d, t, i) \ diff --git a/xen/include/asm-x86/page.h b/xen/include/asm-x86/page.h index eb33dd3eb9..bac99aedad 100644 --- a/xen/include/asm-x86/page.h +++ b/xen/include/asm-x86/page.h @@ -191,6 +191,10 @@ typedef struct { u64 pfn; } pagetable_t; #define __pa(x) (virt_to_maddr(x)) #define __va(x) (maddr_to_virt(x)) +/* Convert between Xen-heap virtual addresses and machine frame numbers. */ +#define virt_to_mfn(va) (virt_to_maddr(va) >> PAGE_SHIFT) +#define mfn_to_virt(mfn) (maddr_to_virt(mfn << PAGE_SHIFT)) + /* Convert between machine frame numbers and page-info structures. */ #define mfn_to_page(mfn) (frame_table + (mfn)) #define page_to_mfn(pg) ((unsigned long)((pg) - frame_table)) diff --git a/xen/include/public/memory.h b/xen/include/public/memory.h index 723131548a..f2a5c1ca5e 100644 --- a/xen/include/public/memory.h +++ b/xen/include/public/memory.h @@ -97,25 +97,27 @@ typedef struct xen_machphys_mfn_list { DEFINE_GUEST_HANDLE(xen_machphys_mfn_list_t); /* - * Returns the base and size of the specified reserved 'RAM hole' in the - * specified guest's pseudophysical address space. - * arg == addr of xen_reserved_phys_area_t. + * Sets the GPFN at which a particular page appears in the specified guest's + * pseudophysical address space. + * arg == addr of xen_add_to_physmap_t. */ -#define XENMEM_reserved_phys_area 7 -typedef struct xen_reserved_phys_area { - /* Which domain to report about? */ +#define XENMEM_add_to_physmap 7 +typedef struct xen_add_to_physmap { + /* Which domain to change the mapping for. */ domid_t domid; - /* - * Which reserved area to report? Out-of-range request reports - * -ESRCH. Currently no architecture will have more than one reserved area. - */ - unsigned int idx; + /* Source mapping space. */ +#define XENMAPSPACE_shared_info 0 /* shared info page */ +#define XENMAPSPACE_grant_table 1 /* grant table page */ + unsigned int space; - /* Base and size of the specified reserved area. */ - unsigned long first_gpfn, nr_gpfns; -} xen_reserved_phys_area_t; -DEFINE_GUEST_HANDLE(xen_reserved_phys_area_t); + /* Index into source mapping space. */ + unsigned long idx; + + /* GPFN where the source mapping page should appear. */ + unsigned long gpfn; +} xen_add_to_physmap_t; +DEFINE_GUEST_HANDLE(xen_add_to_physmap_t); /* * Translates a list of domain-specific GPFNs into MFNs. Returns a -ve error @@ -140,21 +142,6 @@ typedef struct xen_translate_gpfn_list { } xen_translate_gpfn_list_t; DEFINE_GUEST_HANDLE(xen_translate_gpfn_list_t); -/* - * Sets the GPFN at which the shared_info_page appears in the specified - * guest's pseudophysical address space. - * arg == addr of xen_map_shared_info_t. - */ -#define XENMEM_map_shared_info 9 -typedef struct xen_map_shared_info { - /* Which domain to change the mapping for. */ - domid_t domid; - - /* GPFN where the shared_info_page should appear. */ - unsigned long pfn; -} xen_map_shared_info_t; -DEFINE_GUEST_HANDLE(xen_map_shared_info_t); - #endif /* __XEN_PUBLIC_MEMORY_H__ */ /* -- 2.30.2